/**
 * helper_plugin.c - 辅助工具插件
 * 
 * 提供各种实用工具和辅助函数，展示新框架的灵活性
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <pthread.h>
#include <linux/limits.h> /* 添加PATH_MAX定义 */
#include <openssl/ssl.h>  /* 添加SSL类型定义 */

#include "../../include/hook_framework.h"
#include "helper_functions.h"

/* 插件数据结构 */
typedef struct {
    char output_dir[256];      /* 输出目录 */
    int enable_monitoring;     /* 启用监控 */
    int enable_security;       /* 启用安全检查 */
    int dump_network_packets;  /* 转储网络数据包 */
    int monitor_interval_ms;   /* 监控间隔(毫秒) */
} plugin_config_t;

/* 插件配置 */
static plugin_config_t g_config = {
    .output_dir = "/tmp/hook_helper",
    .enable_monitoring = 1,
    .enable_security = 1,
    .dump_network_packets = 0,
    .monitor_interval_ms = 5000  /* 默认5秒 */
};

/* 监控线程ID */
static pthread_t g_monitor_thread;
static int g_monitoring_active = 0;

/* ==== 辅助函数 ==== */

/**
 * 确保输出目录存在
 */
static void ensure_output_dir(void) {
    if (!helper_path_exists(g_config.output_dir)) {
        if (!helper_mkdir_p(g_config.output_dir, 0755)) {
            log_message(LOG_ERROR, "无法创建输出目录: %s", g_config.output_dir);
        }
    }
}

/**
 * 生成系统报告
 */
static void generate_system_report(void) {
    char report_path[512];
    char hostname[128] = {0};
    char username[128] = {0};
    char datetime[64] = {0};
    
    ensure_output_dir();
    
    helper_get_hostname(hostname, sizeof(hostname));
    helper_get_username(username, sizeof(username));
    helper_get_datetime(datetime, sizeof(datetime), NULL);
    
    snprintf(report_path, sizeof(report_path), "%s/system_report_%s.txt", 
             g_config.output_dir, hostname);
    
    FILE* fp = fopen(report_path, "w");
    if (!fp) {
        log_message(LOG_ERROR, "无法创建系统报告文件: %s", report_path);
        return;
    }
    
    fprintf(fp, "=== 系统报告 生成于 %s ===\n\n", datetime);
    fprintf(fp, "主机名: %s\n", hostname);
    fprintf(fp, "用户名: %s\n", username);
    fprintf(fp, "用户ID: %u\n", helper_get_uid());
    fprintf(fp, "有效用户ID: %u\n", helper_get_euid());
    fprintf(fp, "是否为Root: %s\n", helper_is_root() ? "是" : "否");
    fprintf(fp, "进程ID: %u\n", get_process_id());
    fprintf(fp, "父进程ID: %u\n", getppid());
    
    /* 获取可执行文件路径 */
    char exe_path[256];
    if (get_executable_path(exe_path, sizeof(exe_path))) {
        fprintf(fp, "可执行文件: %s\n", exe_path);
    }
    
    /* 获取工作目录 */
    char cwd[256];
    if (getcwd(cwd, sizeof(cwd))) {
        fprintf(fp, "工作目录: %s\n", cwd);
    }
    
    /* 获取CPU和内存信息 */
    fprintf(fp, "\n=== 资源使用情况 ===\n");
    
    struct rusage usage;
    if (getrusage(RUSAGE_SELF, &usage) == 0) {
        fprintf(fp, "用户CPU时间: %ld.%06ld 秒\n", 
                usage.ru_utime.tv_sec, usage.ru_utime.tv_usec);
        fprintf(fp, "系统CPU时间: %ld.%06ld 秒\n", 
                usage.ru_stime.tv_sec, usage.ru_stime.tv_usec);
        fprintf(fp, "最大RSS: %ld KB\n", usage.ru_maxrss);
        fprintf(fp, "页面错误: %ld\n", usage.ru_majflt);
        fprintf(fp, "块输入操作: %ld\n", usage.ru_inblock);
        fprintf(fp, "块输出操作: %ld\n", usage.ru_oublock);
    }
    
    /* 获取环境变量 */
    fprintf(fp, "\n=== 环境变量 ===\n");
    extern char** environ;
    for (char** env = environ; *env; env++) {
        fprintf(fp, "%s\n", *env);
    }
    
    fclose(fp);
    log_message(LOG_INFO, "系统报告已生成: %s", report_path);
}

/**
 * 转储网络数据包
 */
static void dump_network_packet(const void* data, size_t size, int is_outgoing, 
                               const char* remote_addr, int remote_port) {
    if (!g_config.dump_network_packets || !data || size == 0) return;
    
    ensure_output_dir();
    
    char dump_path[512];
    char datetime[64];
    helper_get_datetime(datetime, sizeof(datetime), "%Y%m%d_%H%M%S");
    
    snprintf(dump_path, sizeof(dump_path), "%s/packet_%s_%s_%s_%d.bin", 
             g_config.output_dir, datetime, 
             is_outgoing ? "out" : "in",
             remote_addr ? remote_addr : "unknown",
             remote_port);
    
    helper_write_file(dump_path, data, size);
    log_message(LOG_INFO, "已转储网络数据包: %s (%zu字节)", dump_path, size);
}

/**
 * 系统监控线程
 */
static void* monitor_thread_func(void* arg) {
    log_message(LOG_INFO, "系统监控线程已启动");
    
    while (g_monitoring_active) {
        /* 收集系统信息并记录 */
        char log_path[512];
        snprintf(log_path, sizeof(log_path), "%s/monitor.log", g_config.output_dir);
        
        /* 获取进程统计信息 */
        char stat_path[64];
        snprintf(stat_path, sizeof(stat_path), "/proc/%d/stat", get_process_id());
        
        char stat_content[1024];
        ssize_t bytes_read = helper_read_file(stat_path, stat_content, sizeof(stat_content) - 1);
        if (bytes_read > 0) {
            stat_content[bytes_read] = '\0';
            helper_log_to_file(log_path, "进程统计: %s", stat_content);
        }
        
        /* 等待下一个监控周期 */
        helper_usleep(g_config.monitor_interval_ms * 1000);
    }
    
    log_message(LOG_INFO, "系统监控线程已停止");
    return NULL;
}

/**
 * 启动监控线程
 */
static void start_monitoring(void) {
    if (g_monitoring_active) return;
    
    g_monitoring_active = 1;
    if (pthread_create(&g_monitor_thread, NULL, monitor_thread_func, NULL) != 0) {
        log_message(LOG_ERROR, "无法创建监控线程");
        g_monitoring_active = 0;
        return;
    }
    
    log_message(LOG_INFO, "系统监控已启动");
}

/**
 * 停止监控线程
 */
static void stop_monitoring(void) {
    if (!g_monitoring_active) return;
    
    g_monitoring_active = 0;
    pthread_join(g_monitor_thread, NULL);
    
    log_message(LOG_INFO, "系统监控已停止");
}

/* ==== 回调函数 ==== */

/**
 * 连接回调 - 记录并可选地转储网络数据
 */
static int connect_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int sockfd = (int)(long)context->args[0];
    const struct sockaddr* addr = (const struct sockaddr*)context->args[1];
    
    /* 只处理IPv4连接 */
    if (addr && addr->sa_family == AF_INET) {
        const struct sockaddr_in* addr_in = (const struct sockaddr_in*)addr;
        char ip_str[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &(addr_in->sin_addr), ip_str, INET_ADDRSTRLEN);
        int port = ntohs(addr_in->sin_port);
        
        /* 记录连接信息 */
        log_message(LOG_INFO, "连接到 %s:%d (套接字: %d)", ip_str, port, sockfd);
        
        /* 解析主机名 */
        char hostname[256] = {0};
        if (helper_reverse_dns(ip_str, hostname, sizeof(hostname))) {
            log_message(LOG_INFO, "主机名: %s", hostname);
            
            /* 检查敏感域名 */
            if (is_sensitive_domain(hostname)) {
                log_message(LOG_WARN, "检测到敏感域名访问: %s", hostname);
            }
        }
        
        /* 更新统计信息 */
        update_connections();
    }
    
    /* 允许连接继续 */
    return HOOK_CONTINUE;
}

/**
 * 发送数据回调 - 记录并可选地转储网络数据
 */
static int send_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int sockfd = (int)(long)context->args[0];
    const void* buf = context->args[1];
    size_t len = (size_t)(long)context->args[2];
    
    /* 记录发送信息 */
    log_message(LOG_DEBUG, "发送数据: 套接字=%d, 大小=%zu字节", sockfd, len);
    
    /* 可选：检查发送的数据内容 */
    if (buf && len > 0) {
        helper_inspect_data("发送数据", buf, len);
    }
    
    /* 更新统计信息 */
    update_bytes_sent(len);
    
    /* 允许发送继续 */
    return HOOK_CONTINUE;
}

/**
 * 接收数据回调 - 记录并可选地转储网络数据
 */
static int recv_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int sockfd = (int)(long)context->args[0];
    void* buf = context->args[1];
    size_t len = (size_t)(long)context->args[2];
    ssize_t result = (ssize_t)(long)context->result;
    
    /* 只处理成功接收的数据 */
    if (result > 0) {
        log_message(LOG_DEBUG, "接收数据: 套接字=%d, 大小=%zd字节", sockfd, result);
        
        /* 可选：检查接收的数据内容 */
        if (buf) {
            helper_inspect_data("接收数据", buf, result);
        }
        
        /* 更新统计信息 */
        update_bytes_received(result);
    }
    
    /* 允许接收继续 */
    return HOOK_CONTINUE;
}

/**
 * SSL读取回调 - 记录并可选地转储加密数据
 */
static int ssl_read_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    SSL* ssl = (SSL*)context->args[0];
    void* buf = context->args[1];
    int len = (int)(long)context->args[2];
    int result = (int)(long)context->result;
    
    /* 只处理成功接收的数据 */
    if (result > 0) {
        log_message(LOG_DEBUG, "SSL接收数据: 大小=%d字节", result);
        
        /* 可选：检查接收的SSL数据内容 */
        if (buf) {
            helper_inspect_data("SSL接收数据", buf, result);
        }
        
        /* 更新统计信息 */
        update_ssl_bytes(result);
    }
    
    /* 允许SSL读取继续 */
    return HOOK_CONTINUE;
}

/**
 * 文件读取回调 - 记录文件内容
 */
static int read_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int fd = (int)(long)context->args[0];
    ssize_t result = (ssize_t)(long)context->result;
    
    /* 只处理成功读取的数据 */
    if (result > 0) {
        /* 检查是否是常规文件 */
        if (helper_is_regular_file(fd)) {
            char path[PATH_MAX] = {0};
            if (helper_get_fd_path(fd, path, sizeof(path))) {
                log_message(LOG_DEBUG, "读取文件: %s, 大小=%zd字节", path, result);
                
                /* 更新统计信息 */
                update_file_read(result);
            }
        }
    }
    
    /* 允许读取继续 */
    return HOOK_CONTINUE;
}

/* ==== 插件初始化和清理 ==== */

/* 插件初始化函数 */
__attribute__((visibility("default")))
int plugin_init(void) {
    /* 输出插件信息 */
    log_message(LOG_INFO, "辅助工具插件初始化");
    
    /* 从环境变量加载配置 */
    const char* output_dir = getenv("HELPER_OUTPUT_DIR");
    if (output_dir) {
        strncpy(g_config.output_dir, output_dir, sizeof(g_config.output_dir) - 1);
    }
    
    const char* enable_monitoring = getenv("HELPER_ENABLE_MONITORING");
    if (enable_monitoring) {
        g_config.enable_monitoring = atoi(enable_monitoring);
    }
    
    const char* enable_security = getenv("HELPER_ENABLE_SECURITY");
    if (enable_security) {
        g_config.enable_security = atoi(enable_security);
    }
    
    const char* dump_packets = getenv("HELPER_DUMP_PACKETS");
    if (dump_packets) {
        g_config.dump_network_packets = atoi(dump_packets);
    }
    
    const char* monitor_interval = getenv("HELPER_MONITOR_INTERVAL");
    if (monitor_interval) {
        g_config.monitor_interval_ms = atoi(monitor_interval);
        if (g_config.monitor_interval_ms < 1000) {
            g_config.monitor_interval_ms = 1000; // 最小1秒
        }
    }
    
    /* 确保输出目录存在 */
    ensure_output_dir();
    
    /* 注册回调函数 */
    register_pre_callback("connect", connect_callback, NULL, 200);
    register_pre_callback("send", send_callback, NULL, 200);
    register_post_callback("recv", recv_callback, NULL, 200);
    register_post_callback("SSL_read", ssl_read_callback, NULL, 200);
    register_post_callback("read", read_callback, NULL, 200);
    
    /* 生成初始系统报告 */
    generate_system_report();
    
    /* 启动监控线程 */
    if (g_config.enable_monitoring) {
        start_monitoring();
    }
    
    /* 记录插件已加载 */
    char log_path[512];
    snprintf(log_path, sizeof(log_path), "%s/plugin.log", g_config.output_dir);
    helper_log_to_file(log_path, "辅助工具插件已加载，版本: 1.0.0");
    
    return 1;
}

/* 插件清理函数 */
__attribute__((visibility("default")))
void plugin_cleanup(void) {
    log_message(LOG_INFO, "辅助工具插件清理");
    
    /* 停止监控线程 */
    if (g_monitoring_active) {
        stop_monitoring();
    }
    
    /* 记录插件已卸载 */
    char log_path[512];
    snprintf(log_path, sizeof(log_path), "%s/plugin.log", g_config.output_dir);
    helper_log_to_file(log_path, "辅助工具插件已卸载");
} 